﻿using System;
using System.Text;

namespace System
{
    /// <summary>
    /// 
    /// </summary>
    public static class XConvert
    {
        #region 十进制
        
        /// <summary>
        /// 四舍五入
        /// </summary>
        /// <param name="decimalValue">declmal 变量</param>
        /// <param name="decimals">declmal 位数</param>
        /// <param name="decimals">布尔值，如果输入值不为0，舍入后为0，返回0.1的decimals的幂</param>
        /// <returns></returns>
        public static decimal Round(decimal decimalValue, int decimals, bool IsNotZero = true)
        {
            decimal rtValue = decimal.Round(decimalValue, decimals, MidpointRounding.AwayFromZero);
            return (IsNotZero && decimalValue != 0 && rtValue == 0) ? (decimal)Math.Pow(0.1, decimals) : rtValue;
        }

        #endregion

        #region 结构体与字节数组转换

        /// <summary>
        /// 将结构体对象转换成字节数组
        /// </summary>
        /// <typeparam name="T"> 结构体类型 </typeparam>
        /// <param name="structure"> 结构体对象 </param>
        /// <returns></returns>
        public static byte[] StructToBytes<T>(T structure) where T : struct
        {
            //  获取对象的非托管大小（以字节为单位）。
            int size = System.Runtime.InteropServices.Marshal.SizeOf(structure);
            //  通过使用指定的字节数，从进程的非托管内存中分配内存。
            IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
            //  将数据从托管对象封送到非托管内存块。
            System.Runtime.InteropServices.Marshal.StructureToPtr(structure, ptr, false);
            //  定义指定大小的的一维数组
            byte[] buffer = new byte[size];
            //  将非托管内存指针数据复制到一维数组中。
            System.Runtime.InteropServices.Marshal.Copy(ptr, buffer, 0, size);
            //  释放以前从进程的非托管内存中分配的内存。
            System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
            //  返回 byte 数组
            return buffer;
        }

        /// <summary>
        /// 将字节数组转换成结构体对象
        /// </summary>
        /// <typeparam name="T"> 结构体类型 </typeparam>
        /// <param name="source"> 字节数组 </param>
        /// <returns></returns>
        public static T BytesToStruct<T>(byte[] source) where T : struct
        {
            //  定义结构体默认值
            T retValue = default(T);
            //  获取对象的非托管大小（以字节为单位）。
            int size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
            //  验证字节数
            if (source == null || source.Length == size)
            {
                //  通过使用指定的字节数，从进程的非托管内存中分配内存。
                IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
                try
                {
                    //  将一维的托管 8 位无符号整数数组中的数据复制到非托管内存指针。
                    System.Runtime.InteropServices.Marshal.Copy(source, 0, ptr, source.Length);
                    //  将数据从非托管内存块封送到新分配的指定类型的托管对象。
                    object obj = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeof(T));
                    //  验证对象类型
                    if (obj != null && obj is T)
                        //  返回结构体对象
                        retValue = (T)obj;
                }
                catch (Exception)
                {
                    return default(T);
                }
                finally
                {
                    //  释放以前从进程的非托管内存中分配的内存。
                    System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr);
                }
            }
            //  返回结构体对象
            return retValue;
        }

        #endregion
    }
}
